package edu.ubb.remeye.security.manager.vnc;

import javax.crypto.SecretKey;

import org.apache.mina.core.session.IoSession;
import org.codecompany.jeha.ExceptionHandler;
import org.codecompany.jeha.core.HandlerUtil;

import edu.ubb.remeye.communication.MessageType;
import edu.ubb.remeye.communication.message.Message;
import edu.ubb.remeye.exception.DESSecurityException;
import edu.ubb.remeye.exception.handler.RemEyeExceptionHandler;
import edu.ubb.remeye.security.manager.AbstractServerSecurity;
import edu.ubb.remeye.security.util.des.DESEncrypter;
import edu.ubb.remeye.server.settings.ServerRuntimeSettings;

/**
 * Server authentication class for VNC security.
 * 
 * @author Andrew Ianicicau
 * 
 */
@ExceptionHandler(handler=RemEyeExceptionHandler.class)
public class ServerVNCAuthenticator extends AbstractServerSecurity {

	///////////////////////////////////////////////////////////////////////////////////
	////	ATTRIBUTES - ServerVNCAuthenticator
	///////////////////////////////////////////////////////////////////////////////////
	
	/**
	 * The key used for encryption.
	 */
	private SecretKey key;
	
	/**
	 * The password encrypted by client.
	 */
	private String encryptedPassword;

	
	
	///////////////////////////////////////////////////////////////////////////////////
	////	CONSTRUCTORS - ServerVNCAuthenticator
	///////////////////////////////////////////////////////////////////////////////////

	public ServerVNCAuthenticator(IoSession session) {
		this.session = session;
	}

	
	
	///////////////////////////////////////////////////////////////////////////////////
	////	METHODS - ServerVNCAuthenticator
	///////////////////////////////////////////////////////////////////////////////////

	/**
	 * Authentication.
	 */
	@Override
	public void run() {
		String serverPassword = ServerRuntimeSettings.getinstance().getServerPassword();
		boolean authenticated = authenticate(serverPassword);
		
		if(authenticated) {
			// setting session attribute showing authentication success
			authenticationSucceeded();
		}
		
		// setting session attribute showing end of authentication
		authenticationFinished();
	}

	/**
	 * Server side authentication algorithm.
	 * @param pass The correct password. 
	 * @return True if authentication ok, else false. 
	 */
	private boolean authenticate(String pass) {
		if(pass != null) {
			try {
				// DES key generation
				key = DESEncrypter.generateSecretKey();
				
				String decrypted = "";
				
				// sending the challenge (key) bytes
				byte[] keyBytes = DESEncrypter.getSecretKeyBytes(key);
				Message keyMessage = new Message(MessageType.AUTHENTICATION, keyBytes);
				session.write(keyMessage);
				
				// waiting for the encrypted password
				while(encryptedPassword == null) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						// no need to do anything
					}
				}
				
				// decrypting the password
				decrypted = DESEncrypter.decrypt(encryptedPassword, key);
				
				// result
				if(decrypted.equals(pass))
					return true;
				else
					return false;
			} catch(DESSecurityException e) {
				HandlerUtil.handle(e);
				session.close(true);
			}
		}
		return false;
	}
	
	/**
	 * Forwarding the encrypted password message.
	 */
	@Override
	public void forwardMessage(Message message) {
		encryptedPassword = new String(message.getMessage());
	}

}
